#include "stdafx.h"
#include "Headers.h"
#include "LocalDataFun.h"
#include "GameFunctions.h"

Sprite* CreateChild(SpritePTR parent, Vector2* pos)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"CreateChild");
#endif

	Sprite* newChild = parent->CreateSprite();
	if (newChild) {
	  newChild->Unused(false);
	  newChild->Visible(true);
	  newChild->Pause(false);
	  newChild->MapPosition(pos->x, pos->y);	
	}
	return newChild;
};

Vector2 GetShortestDir(Vector2 initPos, Vector2 goalPos, int count, Vector2 dir)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"GetShortestDir");
#endif

	int left, right, down, up = 0;
	
	if (CheckCollisionVector(&binaryMap, initPos + Vector2::GetUpVector()) && dir != Vector2::GetUpVector())
	  up = Astar(initPos + Vector2::GetUpVector(), goalPos, count + 1, Vector2::GetDownVector());
	if (CheckCollisionVector(&binaryMap, initPos + Vector2::GetLeftVector()) && dir != Vector2::GetLeftVector())
	  left = Astar(initPos + Vector2::GetLeftVector(), goalPos, count + 1, Vector2::GetRightVector());
	if (CheckCollisionVector(&binaryMap, initPos + Vector2::GetRightVector()) && dir != Vector2::GetRightVector())
	  right = Astar(initPos + Vector2::GetRightVector(), goalPos, count + 1, Vector2::GetLeftVector());
	if (CheckCollisionVector(&binaryMap, initPos + Vector2::GetDownVector()) && dir != Vector2::GetDownVector())
	  down = Astar(initPos + Vector2::GetDownVector(), goalPos, count + 1, Vector2::GetUpVector());
	
	int shortest = min(min(up, down), min(left,right));
	
	if (shortest >= 15)
	{
	  Vector2 output;
	  do {
		output = ConvertToVectorDir(random(4));
	  } while (CheckCollisionVector(&binaryMap, initPos + output) || GetNegativeVector(dir) == output);
	  return output;
	}
	
	if (Vector2::GetUpVector() == shortest)
	  return Vector2::GetUpVector();
	if (Vector2::GetLeftVector() == shortest)
	  return Vector2::GetLeftVector();
	if (Vector2::GetRightVector() == shortest)
	  return Vector2::GetRightVector();
	if (Vector2::GetDownVector() == shortest)
	  return Vector2::GetDownVector();
};

int Astar(Vector2 initPos, Vector2 goalPos, int count, Vector2 dir)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"Astar");
#endif

	if (count >= 15)
	  return 15;
	int left, right, up, down = 35;
	
	if (CheckCollisionVector(&binaryMap, initPos + Vector2::GetUpVector()) && dir != Vector2::GetUpVector())
	  up = Astar(initPos + Vector2::GetUpVector(), goalPos, count + 1, Vector2::GetDownVector());
	if (CheckCollisionVector(&binaryMap, initPos + Vector2::GetLeftVector()) && dir != Vector2::GetLeftVector())
	  left = Astar(initPos + Vector2::GetLeftVector(), goalPos, count + 1, Vector2::GetRightVector());
	if (CheckCollisionVector(&binaryMap, initPos + Vector2::GetRightVector()) && dir != Vector2::GetRightVector())
	  right = Astar(initPos + Vector2::GetRightVector(), goalPos, count + 1, Vector2::GetLeftVector());
	if (CheckCollisionVector(&binaryMap, initPos + Vector2::GetDownVector()) && dir != Vector2::GetDownVector())
	  down = Astar(initPos + Vector2::GetDownVector(), goalPos, count + 1, Vector2::GetUpVector());
	
	return min(min(up, down), min(left,right));
};

Vector2 GetControllerDir()
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"GetControllerDir");
#endif

	Vector2 dir;
	
	if (pKeyboard->IsPressed(DIK_W)) {
	  dir.y = -1;
	}
	else if (pKeyboard->IsPressed(DIK_S)) {
	  dir.y = 1;
	}
	else {
	  dir.y = 0;
	}
	if (pKeyboard->IsPressed(DIK_A)) {
	  dir.x = -1;
	}
	else if (pKeyboard->IsPressed(DIK_D)) {
	  dir.x = 1;
	}
	else {
	  dir.x = 0;  
	}
	if (dir.x != 0 && dir.y != 0) {
	  dir.y = 0;
	}
	
	return dir;
};

Sprite* GetClickedSprite(int x, int y)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"GetClickedSprite");
#endif

	/*
	Go through objMap and check collision with all sprites on map, return colliding object.
	*/
};

Vector2 ConvertToVectorDir(const int dir)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"ConvertToVectorDir");
#endif

	switch(dir)
	{
	case 0:
		return Vector2::GetUpVector();
	case 1:
		return Vector2::GetRightVector();
	case 2:
		return Vector2::GetDownVector();
	case 3:
		return Vector2::GetLeftVector();
	default:
		return Vector2::GetUpVector();
	}
};

bool CheckCollisionTile(const MapData* binaryMap, const Vector2 nextPos)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"CheckCollisionTile");
#endif

	switch(binaryMap->data[(int)nextPos.x][(int)nextPos.y]) {
	case 2:
	  return false;
	default:
	  return true;
	}
	
	return false;
};

Vector2 GetNextTile(const Vector2 pos, const Vector2 dir)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"GetNextTile");
#endif

	Vector2 tilePos;
	tilePos.x = (pos.x + (dir.x * 32)) / 32;
	tilePos.y = (pos.y + (dir.y * 32)) / 32;
	return tilePos;
};

Vector2 ConvertToTile(const Vector2 pos)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"ConvertToTile");
#endif

	Vector2 tilePos;
	tilePos.x = (pos.x) / 32;
	tilePos.y = (pos.y) / 32;
	return tilePos;
};

Vector2 GetRandomDir(Vector2 pos, Vector2 dir)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"GetRandomDir");
#endif

	/*Vector2 newDir = dir;
	switch(rand() % 3)
	{
	case 0:
	  newDir.x = dir.y;
	  newDir.y = dir.x;
	  break;
	case 1:
	  newDir.x = -dir.y;
	  newDir.y = -dir.x;
	default:
	  break;
	}
	
	if (!CheckCollisionTile(&binaryMap, GetCurrentTile(pos) + newDir))
	  GetRandomDir(pos, dir);
	if (newDir.x == -dir.x && newDir.y == -dir.y)
	  GetRandomDir(pos, dir);
	
	return newDir;*/
	
	
	Vector2 randDir = ConvertToVectorDir(random(4));
	while(!CheckCollisionVector(&binaryMap, pos + randDir) || randDir == GetNegativeVector(dir))
	{
	  randDir = ConvertToVectorDir(random(4));
	}
	//Trace2("%f + %f ", dir.x, dir.y);
	return randDir;
};

Sprite** LoadMap(MapData* map)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"LoadMap");
#endif

	Sprite** spriteData = new Sprite*[map->size.x];
	for (int i = 0; i < map->size.x; i++) {
	  spriteData[i] = new Sprite[map->size.y];
	}
	for(int x = 0; x<map->size.x; x++) {
	  for(int y = 0; y<map->size.y;y++) {
		Vector2 pos = {x*32, y*32};
		switch(map->data[x][y]) {
	    case 1:
		  spriteData[x][y] = CreateChild(SpritePTR("Ground"), &pos);
	      break;
		case 2:
		  spriteData[x][y] = CreateChild(SpritePTR("Wall"), &pos);
		  break;
		case 3:
		  spriteData[x][y] = CreateChild(SpritePTR("Ground"), &pos);
		  spriteData[x][y] = CreateChild(SpritePTR("Player"), &pos);
		  break;
		case 4:
		  spriteData[x][y] = CreateChild(SpritePTR("Ground"), &pos);
		  spriteData[x][y] = CreateChild(SpritePTR("Enemy"), &pos);
		  break;
		case 5:
		  spriteData[x][y] = CreateChild(SpritePTR("Ground"), &pos);
		  pos.x += 8; pos.y += 8;
		  spriteData[x][y] = CreateChild(SpritePTR("Shiv"), &pos);
		  break;
		default:
		  spriteData[x][y] = CreateChild(SpritePTR("Ground"), &pos);
		  break;
		}
	  }
	}
	return spriteData;
};

bool CheckForPlayer(Vector2 dir)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"CheckForPlayer");
#endif

	ObjData* plyData = GetObjData(SpritePTR("Player"));
	//TODO
	return false;
};

Vector2 GetNegativeVector(Vector2 vect)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"GetNegativeVector");
#endif

	Vector2 newVect;
	newVect.x = -vect.x;
	newVect.y = -vect.y;
	return newVect;
};

Vector2 GetCurrentTile(const Vector2 pos)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"GetCurrentTile");
#endif

	Vector2 tilePos;
	tilePos.x = pos.x / 32;
	tilePos.y = pos.y / 32;
	return tilePos;
};

bool CheckCollisionVector(const MapData* binaryMap, const Vector2 nextPos)
{
#ifdef ERROR_MESSAGES
	ZeroMemory(&_UE,sizeof(_UE));
	strcpy(_UE.functionName,"CheckCollisionVector");
#endif

	switch(binaryMap->data[(int)nextPos.x / 32][(int)nextPos.y / 32]) {
	case 2:
	  return false;
	default:
	  return true;
	}
	
	return false;
};

